/**
	Basic class for a slider to move between a min and max value
	
	This assumes that the art is oriented vertically, using the height
	of the arrow buttons to determine the position of the elements


	@author Chandler McWilliams
	@version 1.0
	@version 2005-07-04

**/
class timber.ui.control.Slider extends MovieClip
{
	// the three button movieclips
	private var handle;
	private var upArrow:MovieClip;
	private var downArrow:MovieClip;

	// min and max values
	private var minval;
	private var maxval;
	private var range;
	
	// current value
	private var current;
	
	// if i'm dragging
	private var dragging;
	
	// min and max y pos of the handle
	private var handlemin;
	private var handlemax;
	
	// size of scroll channel
	private var channelheight;
	
	// total size of the slider
	private var size;

	// rate that arrows modify scroll
	private var rate = 1;

// ===========================================================
// - CONSTRUCTOR
// ===========================================================
	public function Slider(min, max) {
		current = 0;
		minval = min;
		maxval = max;
		dragging = false;
		updateRange();
		
		// broadcast change messages		
		AsBroadcaster.initialize(this);
		
		// listen to yourself
		this['addListener'](this);
	}


// ===========================================================
// - ACCESSORS
// ===========================================================
	/**
		Set the size of the slider.
		This does not change the actual size of the movieclip,
		that should be handled in the subclasses. Size is used to determine
		the position of the slider head only if downArrow is undefined.

		@param  val new size of slider
	*/
	public function setSize(val) { size = Number(val); }
	
	/**
		Get the size of the slider.
		@return number
	*/
	public function getSize() { return size; }
	
	/**
		Set the scroll rate.

		@param  val scrollrate
	*/
	public function setRate(aValue) { rate = aValue; }
	
	/**
		Get the rate.
		@return number
	*/
	public function getRate() { return rate; }
	
	/**
		Sets the minimum value for the slider.

		@param  val minimum value for the slider
	*/
	public function setMin(val) { minval = Number(val); updateRange(); }

	/**
		Sets the maximum value for the slider.

		@param  val maximum value for the slider
	*/
	public function setMax(val) { maxval = Number(val); updateRange(); }
	
	/**
		Updates the range of the slider
	*/
	private function updateRange() { range = maxval - minval;} 

	/**
		Get the current value of the slider.
		@return number
	*/
	public function getValue() { return current; }
	
	/**
		Set the value of the slider
		@param  val the new value for the slider
	*/
	public function setValue(val) {
		if (val < minval) val = minval;
		if (val > maxval) val = maxval;
		val = Math.round(Number(val));
		if (current == val) return;
		current = val;
		didChange();
	}
	
	/**
		Set the slider value as a percentage of the total range.
		A value of 0 = the min, a value of 100 = max

		@param val percentage of range to set the value to
	*/
	public function setPercentageValue(val) {
		var newval = (range/100 * val) + minval;
		setValue(newval);
	}
	
	/**
		Increment the slider one step.
	*/
	public function increment() { 
		var num = getValue() + getRate();
		if (num > maxval) num = maxval;
		setValue(num); 
	}
	
	/**
		Decrement the slider one step.
	*/
	public function decrement() { 
		var num = getValue() - getRate();
		if (num < minval) num = minval;
		setValue(num); 	
	}



// ===========================================================
// - BROADCAST MESSAGES
// ===========================================================
	/**
		Broadcast a onChange message when the value changes.
	*/
	private function didChange() {
		// move the handle
		if (!dragging) handle.setPosition(handlemin + ((getValue()-minval) * channelheight/range));
		
		// send a message
		this['broadcastMessage']("onChange", getValue());
	}



// ===========================================================
// - SETUP EVERYTHING, also called on load
// ===========================================================
	/**
		Setup the slider.
		Updates the slider and prepares for display. Adds arrow button events
		and sets internal size valriables.

		@param  Param Name Param Desrption
		@return Return Type
	*/
	public function update() {
		// ===========================================================
		// - POSITION ELEMENTS
		// ===========================================================
		// min position of handle which is top arrow height + handlesize/2
		// make sure there are handles though, if not use 0
		var uAh = (typeof upArrow == 'undefined')?0:upArrow._height;
		handle.setPosition(uAh + (handle._height/2));
		handlemin = handle._y;

		// max pos of handle
		// make sure there are handles though, if not use 0
		if (typeof downArrow == 'undefined') {
			var dAh = 0;
			var dAy = getSize();
		} else {
			var dAh = downArrow._height;
			var dAy = downArrow._y;
		}
		handlemax = dAy - (dAh + (handle._height/2));

		// height of scroll channel
		channelheight = (handlemax - handle._y);

		// temp ref for scope
		var self = this;
	
		// add arrow events
		delete(upArrow.onEnterFrame);
		delete(downArrow.onEnterFrame);

		upArrow.onPress = function() {
			this.onEnterFrame = function() {self.decrement();}
			this.onRelease = this.onReleaseOutside = function() {delete(this.onEnterFrame)}
		}
	
		downArrow.onPress = function() {
			this.onEnterFrame = function() {self.increment();}
			this.onRelease = this.onReleaseOutside = function() {delete(this.onEnterFrame)}
		}
	}
	
	public function onLoad() { update(); }

	/**
		Get the current value of the slider.
		@return number
	*/
	public function get value() {
		return current;
	}

	/**
		Set the value of the slider
		@param  val the new value for the slider
	*/
	public function set value(val) {
		super.setValue(val);
	}
	
}
